package com.deep.deepenterpise.service.unit.impl;

import com.deep.deepenterpise.common.DrTransactionCommon;
import com.deep.deepenterpise.common.code.DrCodeMsg;
import com.deep.deepenterpise.common.enums.*;
import com.deep.deepenterpise.common.lock.DrLockConstants;
import com.deep.deepenterpise.common.lock.DrLockService;
import com.deep.deepenterpise.common.page.DrPageHelper;
import com.deep.deepenterpise.common.result.DrResult;
import com.deep.deepenterpise.common.util.DrDateUtil;
import com.deep.deepenterpise.dao.DrGoodsOrderMapper;
import com.deep.deepenterpise.dao.DrSysUserMapper;
import com.deep.deepenterpise.model.bo.DrUserInfoBo;
import com.deep.deepenterpise.model.entity.DrGoodsOrder;
import com.deep.deepenterpise.model.to.unit.DrCarOrderPageTo;
import com.deep.deepenterpise.model.to.unit.DrCheckHouseOrderPageTo;
import com.deep.deepenterpise.model.to.unit.DrCheckHouseOrderTo;
import com.deep.deepenterpise.model.vo.DrPageBaseVo;
import com.deep.deepenterpise.model.vo.unit.DrCarOrderVo;
import com.deep.deepenterpise.model.vo.unit.DrCheckHouseOrderVo;
import com.deep.deepenterpise.service.unit.IDrOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author xyz
 * @version 1.0
 * @title DrOrderServiceImpl
 * @description
 * @create 2024/6/13 14:15
 */
@Service
@Slf4j
public class DrOrderServiceImpl implements IDrOrderService {
    @Resource
    private DrSysUserMapper drSysUserMapper;
    @Resource
    private DrGoodsOrderMapper drGoodsOrderMapper;
    @Resource
    private DrLockService drLockService;
    @Resource
    private DrTransactionCommon drTransactionCommon;

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 创建入户检查订单
     * @Time 14:19 2024/6/13
     * @Param [drUserUuid, drCheckHouseOrderVo]
     */
    @Override
    public DrResult postDrAddCheckHouseOrder(String drUserUuid, DrCheckHouseOrderTo drCheckHouseOrderTo) {
        DrUserInfoBo drUserInfoBo = drSysUserMapper.findByDrUserUuidAndDrStatus(drUserUuid, DrStateEnum.YES.getDrState());
        if (drUserInfoBo == null) {
            return DrResult.error().message("用户不存在");
        }
        // 获取当前时间
        long currentSeconds = DrDateUtil.getCurrentSeconds();
        String drOrderNum = DrOrderTypeEnum.CHECK_HOUSE.getDrCode() + currentSeconds;
        // 加锁
        return drLockService.executeWithLock(DrLockConstants.CREATE_ORDER_LOCK + drOrderNum,
                6, TimeUnit.SECONDS,
                () -> createOrder(drUserUuid, currentSeconds, drOrderNum, drUserInfoBo, drCheckHouseOrderTo));
    }


    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 创建入户检查订单
     * @Time 20:19 2024/6/13
     * @Param [drUserUuid, currentSeconds, drOrderNum,  drUserInfoBo, drCheckHouseOrderVo]
     */
    private DrResult createOrder(String drUserUuid, long currentSeconds, String drOrderNum, DrUserInfoBo drUserInfoBo,
                                 DrCheckHouseOrderTo drCheckHouseOrderTo) {
        // 验证订单号是否重复
        Long drNum = drGoodsOrderMapper.countByDrMasterOrderNum(drOrderNum);
        if (drNum != null && drNum > 0) {
            return DrResult.error(DrCodeMsg.SYSTEM_BUSY_ERR);
        }
        Integer drMemberId = drCheckHouseOrderTo.getDrMemberId();
        if (DrStateEnum.YES.compare(drCheckHouseOrderTo.getDrFirst()) && checkFirst(drMemberId)) {
            return DrResult.error().message("首检订单已存在");
        }
        // 创建订单
        DrGoodsOrder drGoodsOrder = new DrGoodsOrder();
        drGoodsOrder.setDrMasterOrderNum(drOrderNum);
        drGoodsOrder.setDrMemberId(drCheckHouseOrderTo.getDrMemberId().toString());
        drGoodsOrder.setDrAddress(drCheckHouseOrderTo.getDrAddress());
        drGoodsOrder.setDrAddressDetail(drCheckHouseOrderTo.getDrAddressDetail());
        drGoodsOrder.setDrDeliveryTime(String.valueOf(currentSeconds));
        drGoodsOrder.setDrFirst(drCheckHouseOrderTo.getDrFirst());
        drGoodsOrder.setDrPayType(DrPayTypeEnum.NONE.getDrType());
        drGoodsOrder.setDrSecurity(DrSecurityEnum.NO.getDrType());
        drGoodsOrder.setDrType(DrOrderTypeEnum.CHECK_HOUSE.getDrType());
        drGoodsOrder.setDrPayStatus(DrPayStateEnum.PAID.getDrState());
        drGoodsOrder.setDrCourier(drUserUuid);
        drGoodsOrder.setDrCourierName(drUserInfoBo.getDrUserName());
        drGoodsOrder.setDrCourierShop(drUserInfoBo.getDrUnitKey());
        drGoodsOrder.setDrPayTime(currentSeconds);
        return drTransactionCommon.execute("新增入户检查订单", () -> drGoodsOrderMapper.insert(drGoodsOrder));
    }

    /**
     * @return boolean
     * @Auth xyz
     * @Desc //TODO 检查入户检查订单首检是否已经做过
     * @Time 15:25 2024/6/18
     * @Param [drMemberId]
     */
    private boolean checkFirst(Integer drMemberId) {
        return drLockService.executeWithLock(DrLockConstants.CREATE_CHECK_HISTORY_FIRST_LOCK + drMemberId,
                6, TimeUnit.SECONDS,
                () -> {
                    Long num = drGoodsOrderMapper
                            .countByDrMemberIdAndDrOrderTypeAndDrFirst(drMemberId,
                                    DrOrderTypeEnum.CHECK_HOUSE.getDrType(), DrStateEnum.YES.getDrState());
                    return num != null && num > 0;
                });
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 获取入户检查订单列表
     * @Time 20:53 2024/6/13
     * @Param [drUserUuid, drCheckHouseOrderPageTo]
     */
    @Override
    public DrResult postDrCheckHouseOrderList(String drUserUuid, DrCheckHouseOrderPageTo drCheckHouseOrderPageTo) {
        DrUserInfoBo drUserInfoBo = drSysUserMapper.findByDrUserUuidAndDrStatus(drUserUuid, DrStateEnum.YES.getDrState());
        if (drUserInfoBo == null) {
            return DrResult.error().message("员工信息不存在或状态异常");
        }
        drCheckHouseOrderPageTo.setDrUnitKey(drUserInfoBo.getDrUnitKey());
        Integer drIsNowUser = drCheckHouseOrderPageTo.getDrIsNowUser();
        if (drIsNowUser != null && drIsNowUser == 1) {
            drCheckHouseOrderPageTo.setDrCourier(drUserUuid);
        }
        // 获取总页数
        Long count = drGoodsOrderMapper.countByPage(drCheckHouseOrderPageTo);
        DrPageBaseVo drPageBaseVo = new DrPageBaseVo(drCheckHouseOrderPageTo.getDrPage(),
                drCheckHouseOrderPageTo.getDrSize(), count);
        if (count != null && count > 0) {
            RowBounds rowBounds = DrPageHelper
                    .getRowBounds(drCheckHouseOrderPageTo.getDrPage(), drCheckHouseOrderPageTo.getDrSize());
            List<DrCheckHouseOrderVo> drCheckHouseOrderVos = drGoodsOrderMapper
                    .findByPage(rowBounds, drCheckHouseOrderPageTo);
            drPageBaseVo.setDrData(drCheckHouseOrderVos);
        }
        return DrResult.ok().data(drPageBaseVo);
    }

    /**
     * @return com.deep.deepenterpise.common.result.DrResult
     * @Auth xyz
     * @Desc //TODO 查询车辆订单列表
     * @Time 15:38 2024/6/20
     * @Param [drCarOrderPageTo]
     */
    @Override
    public DrResult postDrCarOrderList(DrCarOrderPageTo drCarOrderPageTo) {
        String drDriverId = drCarOrderPageTo.getDrDriverId();
        String drUserPhone = drSysUserMapper.findDrUserPhoneByDrCarAndDrDriverId(drDriverId);
        if (StringUtils.isBlank(drUserPhone)) {
            return DrResult.ok();
        }
        drCarOrderPageTo.setDrUserPhone(drUserPhone);
        // 获取总页数
        Long count = drGoodsOrderMapper.countByDrCarOrderVoByPage(drCarOrderPageTo);
        DrPageBaseVo drPageBaseVo = new DrPageBaseVo(drCarOrderPageTo.getDrPage(),
                drCarOrderPageTo.getDrSize(), count);
        if (count != null && count > 0) {
            RowBounds rowBounds = DrPageHelper
                    .getRowBounds(drCarOrderPageTo.getDrPage(), drCarOrderPageTo.getDrSize());
            List<DrCarOrderVo> drCarOrderVos = drGoodsOrderMapper
                    .findDrCarOrderVoByPage(rowBounds, drCarOrderPageTo);
            drPageBaseVo.setDrData(drCarOrderVos);
        }
        return DrResult.ok().data(drPageBaseVo);
    }
}
